package com.hdsx.netty.rpcserver.netty.handler;

import com.hdsx.netty.protocol.BasicProtocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 占贤银
 * time 2024/8/14 0:07
 * description 生命之灯因热情而点燃，生命之舟因拼搏而前行
 */
public class NettyServerInboundHandler extends ChannelInboundHandlerAdapter {

    private static List<String> classNames = new ArrayList<>();

    private static Map<String, Object> handlerRegistryMaps = new HashMap<>(10);

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("数据读取完毕，");
        ctx.close();
    }

    /**
     * 在进行构建实例时把相关的服务注册到注册中心
     */
    public NettyServerInboundHandler() {
        doScanner("com.hdsx.netty.rpcserver.netty.provider");
        doRegistry();
    }

    private void doRegistry() {
        try {
            for (String className : classNames) {
                Class<?> aClass = Class.forName(className);
                if (aClass.isInterface()) {
                    continue;
                }
                String interName = aClass.getInterfaces()[0].getName();
                handlerRegistryMaps.put(interName, aClass.newInstance());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void doScanner(String packageName) {
        try {
            URL url = this.getClass().getClassLoader()
                    .getResource(packageName.replaceAll("\\.", "/"));
            File file = new File(url.getFile());
            for (File listFile : file.listFiles()) {
                String name = listFile.getName();
                if (listFile.isDirectory()) {
                    // todo 如果是目录，则递归调用
                    doScanner(packageName + "." + name);
                } else if (listFile.isFile()) {
                    // todo 如果是文件，则把class文件保存在classNames集合中
                    if (!name.endsWith(".class")) {
                        continue;
                    }
                    classNames.add((packageName+"."+name).replaceAll(".class", ""));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 建立连接时触发的函数
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        // todo 从客户端读取过来的数据(BasicProtocol)
        try {
            BasicProtocol basicProtocol = (BasicProtocol) msg;
            Object instance = handlerRegistryMaps.get(basicProtocol.getClassName());
            Method method = instance.getClass().getMethod(basicProtocol.getMethodName(), basicProtocol.getParameterType());
            Object result = method.invoke(instance, basicProtocol.getParameterValues());
            ctx.writeAndFlush(result);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 发生异常触发的函数
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.writeAndFlush("Netty服务器，网络不稳定，请耐心等待！");
        ctx.close();
    }
}
